#include <memory>
#include <vector>
#include <iostream>
#include "Utility.hpp"
#include "HttpServer.hpp"

#define SEP "\r\n"

// std::string path = "./test.html"; //3-需求的
std::string webRoot = "./webroot"; // web根目录
const std:: string defaultPage = "/index.html";

// get /a/b/c http/1.0\r\n
// KV关系\r\n
//\r\n
// 参数信息
struct Requset
{
public:
    Requset() {}
    ~Requset() {}
    void Deserialization(std::string &mess)
    {
        // 1.获取请求行
        std::string line = Util::ReadLine(SEP,mess);
        logMessage(Debug,"line: %s",line.c_str());
        Util::SplitFirstLine(line,&_method,&_url,&_httpVersion);
        // 如果用户只输入网址，会传一个"/"，我们但这个是一个目录明显不合理，我们需要有一个默认的首页
        // 网页中默认的首页都是叫index.html
        if(_url == "/")
            _url = defaultPage;

        // 2. 获取KV关系
        while(!line.empty())
        {
            line = Util::ReadLine(SEP,mess);
            _kvs.push_back(line);
        }
    }
    void Print()
    {
        logMessage(Debug,"method %s",_method.c_str());
        logMessage(Debug,"url %s",_url.c_str());
        logMessage(Debug,"httpVersion %s",_httpVersion.c_str());
    
        for(auto kv : _kvs)
        {
            std:: cout << kv << std::endl;
        }
    }

public:
    std::string _method;
    std::string _url;   
    std::string _httpVersion;
    std::vector<std::string> _kvs;
    std::string _path; //最终资源的路径
};




std::string httpResponse(std::string &mess)
{
    // std::cout << mess.c_str() << std::endl;
    std::cout << "--------------" <<std::endl;
    Requset req;
    req.Deserialization(mess);
    req.Print();

    // 4.但这样还远不够，我们要知道当一个http响应发过来时，它会有一个web根目录，去索引资源
    // 上面的方式同样是硬编码式的。
    // 我们需要完成以下需求：
    // 4.1 根据请求，解析出http要获取的是什么资源  ---> 所以我们需要做一个反序列化的过程，提取响应中的内容
    //     如果是"/",则返回一个默认的首页
    // 4.2 如果存在，则返回响应的资源
    // 4.3 如果不存在，我们返回一个404的页面
    std::string body;
    // req._url /a/b/c 这个路径一定是要去web根目录下寻找的！


    req._path = webRoot + req._url; //./webroot/a/b/c
    
    logMessage(Debug,"path %s",req._path.c_str());

    bool f = Util::LoadSorce(body, req._path);
    if(f == false)
    {
        logMessage(Debug,"LoadSorce fail... return null ");
        return "";
    }
    std::string response;
    // 第一部分  状态行
    response += "http/1.0 200 OK"; 
    response += SEP; // 第一部分分隔符


    // 第二部分 请求报头（kv关系）
    response += "Content-Length: ";
    response += std::to_string(body.size());
    // Content-Type每种资源对应的具体类型是需要去找一找的
    response += SEP;
    response += "Content-Type: ";

    // 请求的报文并不是一成不变的，因此我们需要根据反序列化的报文获取，客户端要什么资源
    std::string type = Util::GetType(req._url);
    // response += "text/html";
    response += type;
    response += SEP;
    // 第三部分 空行
    response += SEP; 

    // 第四部分 有效载荷
    response += body;
    response += SEP;
    logMessage(Debug,"response success...");
    return response;
    // return body;
}

int main(int argc, char *argv[])
{
    uint16_t port = atoi(argv[1]);
    std::unique_ptr<httpServer> tsver(new httpServer(httpResponse, port));

    tsver->initServer();
    tsver->startServer();
    return 0;
}

// 记录一下过程
void save()
{
    // 根据http响应的格式，做一个响应
    //  1. 简单响应字符串
    //  std::string body = "hello http"; //有效载荷
    //  2. 硬是编码到string
    //  std::string body = "<head><body><h1>hello file1</h1></body></html></head>";
    //  响应的资源一般都是网页视频音频等，是不可能硬编码到string中的，
    //  这些资源一定是放在文件中的，而要获取资源我们一定是通过，读取
    //  文件的方式，把资源获取下来。
    //  3. 正确获取资源
    // std::string body;
    // Util::LoadSorce(body, path);

    // std::string response;
    // response += "http/1.0 200 OK";
    // response += SEP; // 第一部分分隔符
    // // 一份完整的http响应还需要一些字段
    // // 浏览器怎么知道你有效载荷的大小呢？你是需要告诉浏览器的
    // // 浏览器怎么知道你具体的资源呢？资源有那么多，你的是网页？音频还是视频呢？
    // // 你还需要把有效载荷的类型告诉浏览器
    // response += "Content-Length: ";
    // response += std::to_string(body.size());
    // // Content-Type每种资源对应的具体类型是需要去找一找的
    // response += SEP;
    // response += "Content-Type: ";
    // response += "text/html";
    // response += SEP;

    // response += SEP; // 第三部分空行
    // response += body;
}